/*  ______   ______   ______   ______   ______   __  __   _______    
 * /_____/\ /_____/\ /_____/\ /_____/\ /_____/\ /_/\/_/\ /______/\   
 * \   __\/ \   _ \ \\   _ \ \\    _\/_\   _ \ \\ \ \ \ \\   __\/__ 
 *  \ \ \  __\ \ \ \ \\ \ \ \ \\ \/___/\\ (_) \ \\ \ \ \ \\ \ /____/\
 *   \ \ \/_/\\ \ \ \ \\ \ \ \ \\  ___\/_\  ___\/ \ \ \ \ \\ \\_  _\/
 *    \ \_\ \ \\ \_\ \ \\ \/  | |\ \____/\\ \ \    \ \_\ \ \\ \_\ \ \
 *     \_____\/ \_____\/ \____/_/ \_____\/ \_\/     \_____\/ \_____\/
 *  
 * xutility.h
 * Copyright (c) 2010 CodePug
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 *  * Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include <wininet.h>
#include <winsock2.h>
#include <stdio.h>

#ifndef _UTILITY_H				// If we haven't included this file
#define _UTILITY_H	

#define SERVER "webserver/1.0"
#define PROTOCOL "HTTP/1.0"
#define RFC1123FMT "%a, %d %b %Y %H:%M:%S GMT"
#define PORT 80
BOOL getStringHide(SOCKET s, char *str);


BOOL putString(SOCKET s,char *c);
BOOL getStringln(SOCKET s, char *str);
BOOL _getString(SOCKET s, char *str, BOOL showText, BOOL showReturn);
BOOL putChar(SOCKET s,char c);
BOOL newLine(SOCKET s);
WSADATA *WsaData;
SOCKADDR_IN addr;
LPCWSTR MultiCharToUniChar(char* mbString);

void SuppressReboot()
{
	HKEY key = NULL;
	HRESULT hr = S_OK;
	DWORD value;

	if (SUCCEEDED(hr))
		hr = HRESULT_FROM_WIN32(RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Control\\Power\\State\\Reboot", 0, 0, &key));
	if (SUCCEEDED(hr))
		hr = HRESULT_FROM_WIN32(RegSetValueEx(key, L"Flags", 0, REG_DWORD, (BYTE *)&(value = 0x10000), sizeof(DWORD)));
	if (SUCCEEDED(hr))
		hr = HRESULT_FROM_WIN32(RegSetValueEx(key, L"Default", 0, REG_DWORD, (BYTE *)&(value = 0), sizeof(DWORD)));
	if (key)
		RegCloseKey(key);
}

void alert(LPCWSTR text){
	ZDKSystem_ShowMessageBox(text,MESSAGEBOX_TYPE_OK);
}

	BOOL getStringHide(SOCKET s, char *str){
		return _getString(s, str,FALSE,FALSE);
	}

	BOOL getStringHideln(SOCKET s, char *str){
		return _getString(s, str,FALSE,TRUE);
	}

	BOOL getString(SOCKET s, char *str){
		return _getString(s, str,TRUE,FALSE);
	}

	BOOL getStringln(SOCKET s, char *str){
		return _getString(s, str,TRUE,TRUE);
	}

BOOL _getString(SOCKET s, char *str, BOOL showText, BOOL showReturn){
		int count,
		    recvStatus;
		char tempChar[2];
		// Check the size on this
		static char lastCmd[256]="\0\0";

		// Check socket connection
		if (s == INVALID_SOCKET)
			return FALSE;

		// Initialize variables
		count = 0;
		recvStatus = 0;
		tempChar[0] = 0; //was -1
		memset(str,'\0',strlen(str));

		while (tempChar[0] != 10 || tempChar[0] != '\n'){
			recvStatus = recv(s,tempChar,1,0);
			if (recvStatus == 0 || recvStatus == SOCKET_ERROR ){
				strcpy(str," ");
				closesocket(s);
				return FALSE;
			} else {
				if (isprint(tempChar[0])){
					// Show character on the screen
					if (showText)
						if (!putChar(s,tempChar[0])) return FALSE;

					// Copy character to string str
					str[count]=tempChar[0];
					count++;
					str[count]='\0';

					// Overflow protection
					if (count > 250)
						return FALSE;

					// Exit code if ` pressed
					if (tempChar[0] == '`'){
						strcpy(str,"exit");
						tempChar[0] = '\n';
					}
				} else { // otherwise this isn't a printable character
					if (tempChar[0] == 8 && count>0){
						count--;
						str[count]='\0';
						if (showText)
							if (!putChar(s,(char)8)) return FALSE;
							if (!putChar(s,' ')) return FALSE;
							if (!putChar(s,(char)8)) return FALSE;
					}
					if (tempChar[0] == 27){
						//escape code pressed
						strcpy(str,lastCmd);
						tempChar[0] = '\n';
					}
			    } // end if else

			} // end recv else
		} // end while
		strcpy(lastCmd,str);
		if (showReturn)
			newLine(s);
		return TRUE;
	}

	BOOL putString(SOCKET s,char *c){
		if (s == INVALID_SOCKET)
			return FALSE;
		if (send(s,c,strlen(c),0) == SOCKET_ERROR){
			closesocket(s);
			return FALSE;
		}
		return TRUE;
	}

	BOOL putChar(SOCKET s,char c){
		char ca[1];
		ca[0]=c;
		if (s == INVALID_SOCKET)
			return FALSE;

		if (send(s,ca,1,0) == SOCKET_ERROR){
			closesocket(s);
			return FALSE;
		}
		return TRUE;
	}

	BOOL newLine(SOCKET s){
	char nlStr[2];
	int sendStatus;

	nlStr[0]=(char)10;
	nlStr[1]=(char)13;
	if (s == INVALID_SOCKET)
		return FALSE;

	sendStatus = send (s,nlStr,2,0);
	if ( sendStatus == SOCKET_ERROR || sendStatus == 0){
		closesocket(s);
	 	return FALSE;
	}

	return TRUE;
}
	
LPCWSTR MultiCharToUniChar(char* mbString)
{
	int len = strlen(mbString) + 1;
	wchar_t *ucString = new wchar_t[len];
	mbstowcs(ucString, mbString, len);
	return (LPCWSTR)ucString;
}
#endif